home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "gif.h"
-
- #define MAX_LWZ_BITS 12
-
- static int fresh = NO;
- static int code_size, set_code_size;
- static int max_code, max_code_size;
- static int firstcode, oldcode;
- static int clear_code, end_code;
- static int table[2][(1<< MAX_LWZ_BITS)];
- static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
-
- static unsigned char buffer[280];
- static int curbit, lastbit, done, last_byte;
-
- static void
- initGetCode(void)
- {
- curbit = 0;
- lastbit = 0;
- done = NO;
- }
-
- static int
- GetCode(FILE *fd, int code_size)
- {
- int i, j, ret;
- unsigned char count;
-
- if ( (curbit+code_size) >= lastbit) {
- if (done)
- return -1;
- buffer[0] = buffer[last_byte-2];
- buffer[1] = buffer[last_byte-1];
- if ((count = GetDataBlock(fd, &buffer[2])) == 0)
- done = YES;
- last_byte = 2 + count;
- curbit = (curbit - lastbit) + 16;
- lastbit = (2+count)*8 ;
- }
- ret = 0;
- for (i = curbit, j = 0; j < code_size; ++i, ++j)
- ret |= ((buffer[ i / 8 ] & (1 << (i % 8))) != 0) << j;
- curbit += code_size;
- return ret;
- }
-
-
- static int ZeroDataBlock = NO;
-
- int GetDataBlock(FILE *fd, unsigned char *buf)
- {
- int count;
-
- if ((count = getc(fd)) == EOF)
- return -1;
- ZeroDataBlock = count == 0;
- if ((count != 0) && (! ReadOK(fd, buf, count)))
- return -1;
- return count;
- }
-
-
- int initGifLZW(FILE *fp)
- {
- int i;
-
- if ((set_code_size = getc(fp)) == EOF)
- return EOF;
- code_size = set_code_size+1;
- clear_code = 1 << set_code_size ;
- end_code = clear_code + 1;
- max_code_size = 2*clear_code;
- max_code = clear_code+2;
- fresh = YES;
- sp = stack;
- initGetCode();
- for (i = 0; i < clear_code; ++i) {
- table[0][i] = 0;
- table[1][i] = i;
- }
- for (; i < (1<<MAX_LWZ_BITS); ++i)
- table[0][i] = table[1][0] = 0;
- return 0;
- }
-
- int LWZReadByte(FILE *fd)
- {
- register int i;
- int code, incode;
-
- if (fresh) {
- fresh = NO;
- do {
- firstcode = oldcode = GetCode(fd, code_size);
- } while (firstcode == clear_code);
- return firstcode;
- }
-
- if (sp > stack)
- return *--sp;
-
- while ((code = GetCode(fd, code_size)) >= 0) {
- if (code == clear_code) {
- for (i = 0; i < clear_code; ++i) {
- table[0][i] = 0;
- table[1][i] = i;
- }
- for (; i < (1<<MAX_LWZ_BITS); ++i)
- table[0][i] = table[1][i] = 0;
- code_size = set_code_size+1;
- max_code_size = 2*clear_code;
- max_code = clear_code+2;
- sp = stack;
- firstcode = oldcode = GetCode(fd, code_size);
- return firstcode;
- }
- if (code == end_code) {
- int count;
- unsigned char buf[260];
-
- if (ZeroDataBlock)
- return -2;
- while ((count = GetDataBlock(fd, buf)) > 0)
- ;
- return -2;
- }
-
- incode = code;
- if (code >= max_code) {
- *sp++ = firstcode;
- code = oldcode;
- }
- while (code >= clear_code) {
- *sp++ = table[1][code];
- code = table[0][code];
- }
-
- *sp++ = firstcode = table[1][code];
-
- if ((code = max_code) < (1<<MAX_LWZ_BITS)) {
- table[0][code] = oldcode;
- table[1][code] = firstcode;
- ++max_code;
- if ((max_code >= max_code_size) &&
- (max_code_size < (1<<MAX_LWZ_BITS))) {
- max_code_size *= 2;
- ++code_size;
- }
- }
- oldcode = incode;
- if (sp > stack)
- return *--sp;
- }
- return code;
- }
-